package com.ruoyi.user.controller;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.ruoyi.user.domain.UserOrder;
import com.ruoyi.user.service.IUserOrderService;
import com.ruoyi.user.service.thirdpay.alipay.AlipayService;
import com.ruoyi.user.service.thirdpay.alipay.model.AlipayNotifyStatus;
import com.ruoyi.user.utils.DateUtils;
import com.ruoyi.user.utils.PayChannel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

/**
 * 支付宝支付回调通知控制器
 * 处理支付宝支付成功、退款等回调通知
 *
 * @author houyong
 */
@RestController
@RequestMapping("/notice")
public class AliPayNoticeController {

    // 定义常量
    private static final String SUCCESS_RESPONSE = "success";
    private static final String FAILURE_RESPONSE = "fail";
    //重复通知过滤
    private final Logger logger = Logger.getLogger(AliPayNoticeController.class.getName());

    @Autowired
    private IUserOrderService userOrderService;

    @Autowired
    private AlipayService alipayService;

    /**
     * 支付宝支付成功的回调通知处理
     *
     * @param request  HttpServletRequest对象
     * @param response HttpServletResponse对象
     * @throws IOException IO异常
     */
    @RequestMapping("/web/alipay/webhooks")
    public void alipaySuccessNotice(HttpServletRequest request, HttpServletResponse response) throws IOException {
        PrintWriter out = response.getWriter();
        try {
            Map<String, String> requestMap = getAlipayParameter(request);
            boolean signVerified = verifySignature(requestMap);
            if (signVerified) {
                String orderId = requestMap.get("out_trade_no");
                UserOrder order = userOrderService.findOrderByOrderId(orderId);
                if (requestMap.get("trade_status").equals(AlipayNotifyStatus.TRADE_SUCCESS.getName())) {
                    if (StringUtils.isNotEmpty(requestMap.get("refund_fee"))) {
                        //部分退款成功的异步通知
                        out.print("success");
                        return;
                    }
                    String amount = requestMap.get("total_amount");//系统订单金额
                    String buyerId = requestMap.get("buyer_id");//买家支付宝用户号
                    String buyerLogonId = requestMap.get("buyer_logon_id");//买家支付宝账号
                    String payTimeDate = requestMap.get("gmt_payment");// 交易付款时间
                    String payInfo = requestMap.get("fund_bill_list");//支付金额信息
                    String trade_no = requestMap.get("trade_no");//支付宝交易号
                    Long payTimeL = DateUtils.str2Long(payTimeDate, DateUtils.PATTERN_1);
                    BigDecimal totleFee = new BigDecimal(amount);//订单金额
                    int totalFeeI = new BigDecimal(amount).multiply(BigDecimal.valueOf(100)).intValue();
                    order.setAmount(totalFeeI);
                    order.setAlipayTradeNo(trade_no);
                    order.setChannel(PayChannel.ChannelType.ALIPAY.getValue());
                    order.setBuyerId(buyerId);
                    order.setBuyerLogonId(buyerLogonId);
                    order.setTradeType(payInfo);
                    order.setPayTime(payTimeL);
                    order.setStatus(PayChannel.TransactionStatus.PAYSUCCESS.getValue());
                    order.setResult(JSON.toJSONString(requestMap));
                    userOrderService.thirdPaySuccess(order, totalFeeI, payTimeL);
                    out.print("success");
                } else if (requestMap.get("trade_status").equals(AlipayNotifyStatus.WAIT_BUYER_PAY.getName())) {
                    out.print(SUCCESS_RESPONSE);
                } else if (requestMap.get("trade_status").equals(AlipayNotifyStatus.TRADE_FINISHED.getName())) {
                    // 订单就不能再进行退款了
                    out.print(SUCCESS_RESPONSE);
                } else if (requestMap.get("trade_status").equals(AlipayNotifyStatus.TRADE_CLOSED.getName())) {
                    out.print(SUCCESS_RESPONSE);
                    if (StringUtils.isNotEmpty(requestMap.get("refund_fee"))) {
                        //全额退款成功的异步通知
                        String gmtRefundDateTime = requestMap.get("gmt_refund");
                        Long refundTime = DateUtils.str2Long(gmtRefundDateTime, DateUtils.PATTERN_1);
                        // 更新退款时间
                        out.print(SUCCESS_RESPONSE);
                    } else {
                        //未在指定时间段内未支付时关闭的交易
                        out.print(SUCCESS_RESPONSE);
                    }
                } else {
                    // 交易类型 不包含这4种类型
                    out.print(FAILURE_RESPONSE);
                }
            } else {
                logger.warning("支付宝回调签名验证失败");
                out.print(FAILURE_RESPONSE);
            }
        } catch (Exception e) {
            logger.severe("处理支付宝回调通知异常: " + e.getMessage());
            e.printStackTrace();
            out.print("failure");
        }
    }

    /**
     * 验证来自支付宝的回调通知的签名真实性
     *
     * @param resultMap 回调通知的数据
     * @return 签名是否验证通过
     */
    private boolean verifySignature(Map<String, String> resultMap) {
        try {
            boolean verified = alipayService.checksignVerified(resultMap);
            logger.info("--------验签结果--->" + verified);
            return verified;
        } catch (AlipayApiException e) {
            logger.severe("支付宝签名验证异常: " + e.getMessage());
            return false;
        }
    }

    /**
     * 从支付宝异步通知中提取请求参数
     *
     * @param request HttpServletRequest对象
     * @return 参数映射
     */
    private Map<String, String> getAlipayParameter(HttpServletRequest request) {
        Map properties = request.getParameterMap();
        Map<String, String> paramsMap = new HashMap<>();
        Iterator entries = properties.entrySet().iterator();
        Map.Entry entry;
        String name = "";
        String value = "";
        while (entries.hasNext()) {
            entry = (Map.Entry) entries.next();
            name = (String) entry.getKey();
            Object valueObj = entry.getValue();
            if (null == valueObj) {
                value = "";
            } else if (valueObj instanceof String[]) {
                String[] values = (String[]) valueObj;
                for (int i = 0; i < values.length; i++) {
                    value = values[i] + ",";
                }
                value = value.substring(0, value.length() - 1);
            } else {
                value = valueObj.toString();
            }
            paramsMap.put(name, value);
        }
        Set<String> key = paramsMap.keySet();
        for (Iterator<String> it = key.iterator(); it.hasNext(); ) {
            String s = it.next();
            logger.info(s + ":" + paramsMap.get(s));
        }
        return paramsMap;
    }

//    /**
//     * 测试接口 - 无需签名验证
//     *
//     * @return 测试结果
//     */
//    @GetMapping("/test/alipay/notify")
//    public AjaxResult test(HttpServletRequest request) {
//        Map<String, String> requestMap = getAlipayParameter(request);
//
//            String orderId = requestMap.get("out_trade_no");
//            UserOrder order = userOrderService.findOrderByOrderId(orderId);
//            if (requestMap.get("trade_status").equals(AlipayNotifyStatus.TRADE_SUCCESS.getName())) {
//                if (StringUtils.isNotEmpty(requestMap.get("refund_fee"))) {
//                    return AjaxResult.success("退款了");
//                }
//                String amount = requestMap.get("total_amount");//系统订单金额
//                String buyerId = requestMap.get("buyer_id");//买家支付宝用户号
//                String buyerLogonId = requestMap.get("buyer_logon_id");//买家支付宝账号
//                String payTimeDate = requestMap.get("gmt_payment");// 交易付款时间
//                String payInfo = requestMap.get("fund_bill_list");//支付金额信息
//                String trade_no = requestMap.get("trade_no");//支付宝交易号
//                Long payTimeL = DateUtils.str2Long(payTimeDate, DateUtils.PATTERN_1);
//                BigDecimal totleFee = new BigDecimal(amount);//订单金额
//                int totalFeeI = new BigDecimal(amount).multiply(BigDecimal.valueOf(100)).intValue();
//                order.setAmount(totalFeeI);
//                order.setAlipayTradeNo(trade_no);
//                order.setChannel(PayChannel.ChannelType.ALIPAY.getValue());
//                order.setBuyerId(buyerId);
//                order.setBuyerLogonId(buyerLogonId);
//                order.setTradeType(payInfo);
//                order.setPayTime(payTimeL);
//                order.setStatus(PayChannel.TransactionStatus.PAYSUCCESS.getValue());
//                order.setResult(JSON.toJSONString(requestMap));
//                userOrderService.thirdPaySuccess(order, totalFeeI, payTimeL);
//            } else if (requestMap.get("trade_status").equals(AlipayNotifyStatus.WAIT_BUYER_PAY.getName())) {
//            } else if (requestMap.get("trade_status").equals(AlipayNotifyStatus.TRADE_FINISHED.getName())) {
//            } else if (requestMap.get("trade_status").equals(AlipayNotifyStatus.TRADE_CLOSED.getName())) {
//                if (StringUtils.isNotEmpty(requestMap.get("refund_fee"))) {
//                    //全额退款成功的异步通知
//                    String gmtRefundDateTime = requestMap.get("gmt_refund");
//                    Long refundTime = DateUtils.str2Long(gmtRefundDateTime, DateUtils.PATTERN_1);
//                    // 更新退款时间
//                } else {
//                    //未在指定时间段内未支付时关闭的交易
//                }
//            } else {
//                // 交易类型 不包含这4种类型
//            }
//
//        return AjaxResult.success("测试接口调用成功");
//    }
}